package com.qudian.pay.log.aop;

import java.net.InetAddress;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.qudian.pay.core.aop.BaseInterceptor;
import com.qudian.pay.core.diagnostic.Profiler;
import com.qudian.pay.core.runtime.MdcHolder;
import com.qudian.pay.core.runtime.ProductContext;
import com.qudian.pay.core.runtime.ProductContextHolder;
import com.qudian.pay.core.runtime.ProductEnvironment;
import com.qudian.pay.core.utils.IPUtils;

/**
 * @Description: Schedule层性能日志拦截器
 * @ClassName: PerformanceServiceInterceptor
*
 * @date 2015年11月17日 下午10:32:33
 */ 
public class PerformanceScheduleInterceptor extends BaseInterceptor {
	
	private final static Logger logger = LoggerFactory.getLogger("PERFORM");
	
	/**
	 * @Fields threshold : 以毫秒表示的阈值
	 */ 
	private int threshold = 5000;
	
	@Override
	public Object bizInvoke(MethodInvocation invocation) throws Throwable {
		//针对线程池 任务调度作为入口 清空环境信息
		ProductContextHolder.clean();
		ProductContext productContext = ProductContextHolder.getProductContext();
		productContext.setEnvironment(new ProductEnvironment(IPUtils.getIp4Single(), IPUtils.getIp4Single(), InetAddress.getLocalHost().getHostName()));
		MdcHolder.init(productContext);
		StringBuilder builder = new StringBuilder(64);
		builder.append(invocation.getMethod().getDeclaringClass().getName()).append(".").append(invocation.getMethod().getName());
		String name = builder.toString();
		Profiler.start("Invoking Schedule method: " + name);
		try {
			return invocation.proceed();
		} finally {
			Profiler.release();
			long elapseTime = Profiler.getDuration();
			//如果方法调用时间超过 阈值,或者加入了PerformLog注解 则打印service性能日志
			if (elapseTime > threshold ) {
				StringBuilder builderTmp = new StringBuilder();
				builderTmp.append(" Start Schedule Task : " + invocation.getMethod().getDeclaringClass().getName())
				// 阈值时间
				.append(" threshold = ").append(threshold).append("ms,");
				// 实际执行时间为
				builderTmp.append(" used = ").append(elapseTime).append("ms.\r\n");
				builderTmp.append(Profiler.dump());
				logger.info(builderTmp.toString());
			}
			//清空线程变量副本 针对单线程问题
			Profiler.reset();
			MdcHolder.clean();
			ProductContextHolder.clean();
		}
		
	}
	
	public void setThreshold(int threshold) {
		this.threshold = threshold;
	}
}
